public class Rule{
	public static final int SINGLE=1;
	public static final int PAIR=2;
	public static final int TRIPLET=3;
	public static final int TRIPLET_SINGLE=4;
	public static final int TRIPLET_PAIR=5;
	public static final int SEQUENCE=6;
	public static final int PAIR_SEQUENCE=7;
	public static final int TRIPLET_SEQUENCE=8;
	public static final int TRIPLET_SEQUENCE_SINGLE=9;
	public static final int TRIPLET_SEQUENCE_PAIR=10;
	public static final int BOMB=11;
	public static final int ROCKET=12;
	public static final int QUAD_SINGLE=13;
	public static final int QUAD_PAIR=14;
	public static final int UNKNOWN=15;
	public static final int ILLEGAL = -1;
	
	public static CardType getType(int [] cards){
		int [] temp=new int[cards.length];
		
		for(int i=0;i<cards.length;i++){
			if(cards[i]<53) temp[i]=(cards[i]-1)/4;
			else if(cards[i]==53)temp[i] = 13;
			else if(cards[i]==54)temp[i] = 14;
			}
			
		if(temp.length==1) return new CardType(SINGLE,temp[0],1);//SINGLE
		if(temp.length==2){
			if(isPair(temp))return new CardType(PAIR,temp[0],2);//PAIR
			else if(isRocket(temp)) return new CardType(ROCKET,temp[0],2);//ROCKET;
			else return new CardType(ILLEGAL,temp[temp.length-1],2);//ILLEGAL;
		}
		if(temp.length==3) {
			if(isTriplet(temp)) return new CardType(TRIPLET,temp[0],3);//TRIPLET;
			else return new CardType(ILLEGAL);//ILLEGAL;	
		}
		if(temp.length==4){
			if(temp[0]!=temp[1]&&temp[1]==temp[2]&&temp[2]==temp[3]) return new CardType(TRIPLET_SINGLE,temp[3],4);//TRIPLET_SINGLE;
			else if(temp[0]==temp[1]&&temp[1]==temp[2]&&temp[2]!=temp[3]) return new CardType(TRIPLET_SINGLE,temp[0],4);//TRIPLET_SINGLE;
			else if(isBomb(temp)) return new CardType(BOMB,temp[0],4);//BOMB;
			else return new CardType(ILLEGAL);//ILLEGAL;
		}
		if(temp.length==5){
			if(isSequence(temp)) return new CardType(SEQUENCE,temp[4],5);//SEQUENCE;
			else if(temp[0]==temp[1]&&temp[2]==temp[3]&&temp[3]==temp[4]) return new CardType(TRIPLET_PAIR,temp[4],5);//TRIPLET_PAIR;
			else if(temp[0]==temp[1]&&temp[1]==temp[2]&&temp[3]==temp[4]) return new CardType(TRIPLET_PAIR,temp[0],5);//TRIPLET_PAIR;
			else return new CardType(ILLEGAL);//ILLEGAL;	
			}
		if(temp.length==6){
			if(isSequence(temp)) return new CardType(SEQUENCE,temp[5],6);//SEQUENCE;
			else if(isPairSequence(temp)) return new CardType(PAIR_SEQUENCE,temp[5],6);
			else if(isTripletSequence(temp)) return new CardType(TRIPLET_SEQUENCE,temp[5],6);//TRIPLET_SEQUENCE;
			else if(isQuadSingle(temp)) return new CardType(QUAD_SINGLE,temp[2],6);
			else return new CardType(ILLEGAL);//ILLEGAL;	
			}
		if(temp.length>6){
			if(isSequence(temp)) return new CardType(SEQUENCE,temp[temp.length-1],temp.length);//SEQUENCE;
			else if(isPairSequence(temp)) return new CardType(PAIR_SEQUENCE,temp[temp.length-1],temp.length);
			else if(isTripletSequenceSingle(temp).type==TRIPLET_SEQUENCE_SINGLE) return isTripletSequenceSingle(temp);
			else if(isTripletSequence(temp)) return new CardType(TRIPLET_SEQUENCE,temp[temp.length-1],temp.length);
			else if(isTripletSequencePair(temp).type==TRIPLET_SEQUENCE_PAIR) return isTripletSequencePair(temp);
			else if(isQuadPair(temp).type==QUAD_PAIR) return isQuadPair(temp);
			else return new CardType(ILLEGAL);//ILLEGAL;	
			}		
	return new CardType(ILLEGAL);//ILLEGAL;	
	}
	
	public static int compare(int []cards1,int [] cards2){
		CardType ct1=getType(cards1);Debug.println("line 70,cards1[0]:"+cards1[0]);
		CardType ct2=getType(cards2);Debug.println("line 71:cards2[0]"+cards2[0]);
		if(ct1.type==ILLEGAL||ct2.type==ILLEGAL) return -1;
		else if(ct1.type==ct2.type&&ct1.mainCard>ct2.mainCard) return 1;
		else if(ct1.type==ROCKET) return 1;
		else if(ct1.type==BOMB&&ct2.type!=ROCKET) return 1;
		return 0;
	}
	
	private static boolean isSequence(int[] cards){
		boolean b=true;
		if(cards.length<5) return false;
		else if(cards[cards.length-1]>=12) return false;
		else {
			for(int i=0;i<cards.length-1;i++){
				if((cards[i+1]-cards[i])!=1) {
					b=false;break;
				}
			}	
		}
		return b;
	}
	
	private static boolean isPair(int [] cards,int from,int to){
		Debug.println("In Rule.isPair,cards=",cards);
		Debug.println("from="+from);
		Debug.println("to="+to);
		if ((to-from)!=2) return false;
		else if(cards[from]>12) return false;
		else if(cards[from]==cards[to-1]) return true;
		else return false;
		}
	private static boolean isPair(int [] cards){
		return isPair(cards,0,cards.length);
		}
	private static boolean isPairSequence(int[] cards,int from,int to){
		if(to-from<6) return false;
		else if((to-from)%2!=0) return false;
		else if(cards[to-1]>=12) return false;
		else{
			for(int i=0;i<(to-from)/2;i++){
				if(!isPair(cards,from+i*2,from+(i+1)*2)) return false;
			}
			for(int i=0;i<(to-from)/2-1;i++){
				if(cards[from+(i+1)*2]-cards[from+i*2]!=1) return false;
			}
		}
		return true;
	}
	
	private static boolean isPairSequence(int [] cards){
		return isPairSequence(cards,0,cards.length);
	}
	
	private static boolean isRocket(int [] cards){
		if(cards==null||cards.length!=2) return false;
		else if(cards[0]==13&&cards[1]==14) return true;
		else return false;
		}	
	
	private static boolean isTriplet(int [] cards,int from,int to){
		if((to-from)!=3) return false;
		else if(cards[from]==cards[from+1]&&cards[from+1]==cards[to-1]) return true;
		else return false;
		}
	private static boolean isTriplet(int [] cards){
		return isTriplet(cards,0,cards.length);
		}
	private static boolean isTripletSequence(int [] cards,int from,int to){
		Debug.println("In Rule.isTripletSequence,cards=",cards);
		Debug.println("from="+from);
		Debug.println("to="+to);
		if((to-from)<6) return false;
		else if(((to-from)%3)!=0) return false;
		else if(cards[to-1]>=12) return false;
		else {
			for(int i=0;i<(to-from)/3;i++){
				if(!isTriplet(cards,from+i*3,from+(i+1)*3)) return false;
			}
			for(int i=0;i<(to-from)/3-1;i++){
				if(cards[from+(i+1)*3]-cards[from+i*3]!=1) return false;
			}			
		}	
		return true;	
	}
	private static boolean isTripletSequence(int [] cards){
		return isTripletSequence(cards,0,cards.length);
		}
		
	private static CardType isTripletSequenceSingle(int [] cards){
		Debug.println("In Rule.isTripletSequenceSingel,cards=",cards);
		if(cards.length<8) return new CardType(UNKNOWN);
		else if((cards.length%4)!=0) return new CardType(UNKNOWN);
		else{
			int length=(cards.length/4)*3;
			for(int i=0;i+length<=cards.length;i++){
				if(isTripletSequence(cards,i,i+length)) return new CardType(TRIPLET_SEQUENCE_SINGLE,cards[i+length-1],cards.length);
			}
			return new CardType(UNKNOWN);
		}
	}
	
	private static CardType isTripletSequencePair(int[] cards){
		Debug.println("In Rule.isTripletSequencePair,cards=",cards);
		if(cards.length<10) return new CardType(UNKNOWN);
		else if((cards.length%5)!=0) return new CardType(UNKNOWN);
		else{
			int length=(cards.length/5)*3;
			for(int i=0;i+length<=cards.length;i=i+2){
				if(isTripletSequence(cards,i,i+length)){
					 int [] newCards=new int[cards.length-length];
					 System.arraycopy(cards,0,newCards,0,i);
					 System.arraycopy(cards,i+length,newCards,i,cards.length-length-i);
					 for(int j=0;j<length/3;j++)
					 	if(!isPair(newCards,j*2,(j+1)*2)) return new CardType(UNKNOWN);
					 return new CardType(TRIPLET_SEQUENCE_PAIR,cards[i+length-1],cards.length);
				}
			
			}
			return new CardType(UNKNOWN);
		}
	}
	
	private static CardType isQuadPair(int [] cards){
		if(cards==null||cards.length!=8) return new CardType(UNKNOWN);
		else{
			for(int i=0;i<3;i++)
				if(isBomb(cards,i*2,4+i*2)){
					int [] newCards=new int[4];
					System.arraycopy(cards,0,newCards,0,i);
					System.arraycopy(cards,i+4,newCards,i,4-i);
					if(!isPair(newCards,0,2)) return new CardType(UNKNOWN);
					if(!isPair(newCards,2,4)) return new CardType(UNKNOWN);
					return new CardType(QUAD_PAIR,cards[i*2],8);					
				}
			return new	CardType(UNKNOWN);	
		}
	}
	
	private static boolean isBomb(int [] cards,int from,int to){
		if(cards==null||from<0||to>cards.length||to-from!=4) return false;
		else if(cards[from+0]==cards[from+1]&&cards[from+1]==cards[from+2]&&cards[from+2]==cards[from+3]) return true;
		return false;
	}
	
	private static boolean isBomb(int [] cards){
		return isBomb(cards,0,cards.length);
	}
	
	private static boolean isQuadSingle(int [] cards){
		if(cards==null||cards.length!=6) return false;
		for(int i=0;i<3;i++) if(isBomb(cards,i,i+4)) return true;
		return false;
	}
	
	private static int find(int n1,int n2,int from,int to,int []numArray){
		//
		if(numArray==null||numArray.length!=15||from<0||to>15||to-from<0) return -1;
		for(int i=from;i<to;i++){
			if(numArray[i]>=n1&&numArray[i]<=n2) return i;
		}
		return -1;
	}
	
	private static int [] getNumArray(int []cards){
		if(cards==null) return null;
		int [] numArray=new int[15];
		for(int i=0;i<cards.length;i++){
			if((cards[i]-1)/4<=12) numArray[(cards[i]-1)/4]++;
			else if(cards[i]==53) numArray[13]++;
			else if(cards[i]==54) numArray[14]++;
		}
		return numArray;
	}
	
	public static int [] canPlay(int [] fromCards,int [] curCards){
		CardType cardType=getType(curCards);
		if(cardType.type==ILLEGAL) return null;
		int[] newCards;
		int [] numArray=getNumArray(fromCards);
		int index;
		switch(cardType.type){
			case SINGLE:{
				index=findSingle(numArray,cardType.mainCard+1);//find(1,4,cardType.mainCard+1,15,numArray);
				//if(index==-1) return null;
				//else return getCards(fromCards,new CardType(SINGLE,index,1));
				if(index!=-1) return getCards(fromCards,new CardType(SINGLE,index,1));
				return getBombOrRocket(fromCards);
			}
			case PAIR:{
				index=findPair(numArray,cardType.mainCard+1);//find(2,4,cardType.mainCard+1,13,numArray);
				//if(index==-1) return null;
				//else return getCards(fromCards,new CardType(PAIR,index,2));
				if(index!=-1) return getCards(fromCards,new CardType(PAIR,index,2));
				return getBombOrRocket(fromCards);
			}
			case TRIPLET:{
				index=findTriplet(numArray,cardType.mainCard+1);//find(3,4,cardType.mainCard+1,13,numArray);
				//if(index==-1) return null;
				//else return getCards(fromCards,new CardType(TRIPLET,index,3));
				if(index!=-1) return getCards(fromCards,new CardType(TRIPLET,index,3));
				return getBombOrRocket(fromCards);
			}
			case TRIPLET_SINGLE:{
				index=findTriplet(numArray,cardType.mainCard+1);//find(3,4,cardType.mainCard+1,13,numArray);
				//if(index==-1) return null;
				if(index!=-1)
				/*else*/{
					int index2=findSingle(numArray,0);//find(1,2,0,index,numArray);
					if	(index2==index) index2=findSingle(numArray,index+1);
					if(index2!=-1){
						newCards=new int[4];
						Debug.println("Triplet_",getCards(fromCards,new CardType(TRIPLET,index,3)));
						Debug.println("single:",getCards(fromCards,new CardType(SINGLE,index2,1)));
						System.arraycopy(getCards(fromCards,new CardType(TRIPLET,index,3)),0,newCards,0,3);
						System.arraycopy(getCards(fromCards,new CardType(SINGLE,index2,1)),0,newCards,3,1);
						java.util.Arrays.sort(newCards);
						return newCards;
					}
					
					//else return null;
				}
				return getBombOrRocket(fromCards);
			}
			case TRIPLET_PAIR:{
				index =findTriplet(numArray,cardType.mainCard+1);//find(3,4,cardType.mainCard+1,13,numArray);
				//if(index==-1) return null;
				if(index!=-1)
				/*else*/{
					int index2=findPair(numArray,0);
					if(index2==index) index2=findPair(numArray,index+1);
					if(index2!=-1){
						newCards=new int[5];
						System.arraycopy(getCards(fromCards,new CardType(TRIPLET,index,3)),0,newCards,0,3);
						System.arraycopy(getCards(fromCards,new CardType(PAIR,index2,2)),0,newCards,3,2);
						java.util.Arrays.sort(newCards);
						return newCards;
					}
					//else return null;
				}
				return getBombOrRocket(fromCards);
			}
			case SEQUENCE:{
				int length=cardType.cardNum;
				int start=cardType.mainCard-length+1;
				index=findSequence(numArray,start+1,length); //3,4,5,6,7;length=5;start=7-5+1=3;
				if(index==-1) return getBombOrRocket(fromCards);//null;
				newCards=getCards(fromCards,new CardType(SEQUENCE,index+length-1,length));
				java.util.Arrays.sort(newCards);
				return newCards;
			}
			case PAIR_SEQUENCE:{
				int length=cardType.cardNum/2;
				int start=cardType.mainCard-length+1;
				index=findPairSequence(numArray,start+1,length);
				if(index==-1) return getBombOrRocket(fromCards);//null;
				newCards=getCards(fromCards,new CardType(PAIR_SEQUENCE,index+length-1,length*2));
				if (newCards==null) return null;
				java.util.Arrays.sort(newCards);
				return newCards;
			}
			case TRIPLET_SEQUENCE:{
				int length=cardType.cardNum/3;
				int start=cardType.mainCard-length+1;
				index=findTripletSequence(numArray,start+4,length);
				if(index==-1) return getBombOrRocket(fromCards);//null;
				newCards=getCards(fromCards,new CardType(TRIPLET_SEQUENCE,index+length-1,length*3));
				if(newCards==null) return getBombOrRocket(fromCards);//null;
				java.util.Arrays.sort(newCards);
				return newCards;
			}
			case TRIPLET_SEQUENCE_SINGLE:{
				int length=cardType.cardNum/4;
				int start=cardType.mainCard-length+1;
				index=findTripletSequence(numArray,start+4,length);Debug.println("Rule,line334:index="+index);
				if(index==-1) return getBombOrRocket(fromCards);//null;;
				int [] tempCards=getCards(fromCards,new CardType(TRIPLET_SEQUENCE,index+length-1,length*3));Debug.println("line,336+tempCards:",tempCards);				
				if (tempCards==null) return getBombOrRocket(fromCards);//null;
				java.util.Arrays.sort(tempCards);
				newCards=new int[cardType.cardNum];
				System.arraycopy(tempCards,0,newCards,0,length*3);
				tempCards=removeCards(fromCards,tempCards);
				for(int i=0;i<length;i++){
					int index2=findSingle(getNumArray(tempCards),0);Debug.println("line:343;index2;"+index2);
					if (index2==-1) return getBombOrRocket(fromCards);//null;
					int []single=getCards(tempCards,new CardType(SINGLE,index2,1));
					if (single==null) return getBombOrRocket(fromCards);//null;
					System.arraycopy(single,0,newCards,length*3+i,1);
					tempCards=removeCards(tempCards,single);
				}
				java.util.Arrays.sort(newCards);
				return newCards;				
			}
			case TRIPLET_SEQUENCE_PAIR:{
				int length=cardType.cardNum/5;
				int start=cardType.mainCard-length+1;
				index=findTripletSequence(numArray,start+4,length);
				if(index==-1) return getBombOrRocket(fromCards);//null;
				int [] tempCards=getCards(fromCards,new CardType(TRIPLET_SEQUENCE,index+length-1,length*3));
				if (tempCards==null) return getBombOrRocket(fromCards);//null;
				java.util.Arrays.sort(tempCards);
				newCards=new int[cardType.cardNum];
				System.arraycopy(tempCards,0,newCards,0,length*3);
				tempCards=removeCards(fromCards,tempCards);
				for(int i=0;i<length;i++){
					int index2=findPair(getNumArray(tempCards),0);
					if (index2==-1) return getBombOrRocket(fromCards);//null;
					int []pair=getCards(tempCards,new CardType(PAIR,index2,2));
					if (pair==null) return getBombOrRocket(fromCards);//null;
					System.arraycopy(pair,0,newCards,length*3+i*2,2);
					tempCards=removeCards(tempCards,pair);
				}
				java.util.Arrays.sort(newCards);
				return newCards;
			}
			case BOMB:{				
				index=findQuad(numArray,cardType.mainCard+1);
				if(index==-1)return getRocket(fromCards);
				return getCards(fromCards,new CardType(BOMB,index,4));				
			}
			case QUAD_SINGLE:{
				index=findQuad(numArray,cardType.mainCard+1);Debug.println("line,381,index"+index);
				if(index==-1) return getBombOrRocket(fromCards);//null;
				int [] tempCards=getCards(fromCards,new CardType(BOMB,index,4));Debug.println("line,383,tempCards",tempCards);
				if(tempCards==null) return getBombOrRocket(fromCards);//null;
				newCards=new int[6];
				System.arraycopy(tempCards,0,newCards,0,4);Debug.println("line,386,newCards:",newCards);
				tempCards=removeCards(fromCards,tempCards);Debug.println("line,387,tempCards:",tempCards);
				for(int i=0;i<2;i++){
					int index2 = findSingle(getNumArray(tempCards),0);Debug.println("line,389,index2:"+index2);
					if(index2==-1) return getBombOrRocket(fromCards);//null;
					int []single=getCards(tempCards,new CardType(SINGLE,index2,1));Debug.println("line,391,single:",single);
					if(single==null) return getBombOrRocket(fromCards);//null;
					System.arraycopy(single,0,newCards,4+i,1);Debug.println("line,393,newCards:",newCards);
					tempCards=removeCards(tempCards,single);Debug.println("line,394,tempCards:",tempCards);
				}
				java.util.Arrays.sort(newCards);Debug.println("line,396,newCards:",newCards);
				return newCards;
			}
			case QUAD_PAIR:{
				index=findQuad(numArray,cardType.mainCard+1);
				if(index==-1) return getBombOrRocket(fromCards);//null;
				int [] tempCards=getCards(fromCards,new CardType(BOMB,index,4));
				if(tempCards==null) return getBombOrRocket(fromCards);//null;
				newCards=new int[8];
				System.arraycopy(tempCards,0,newCards,0,4);
				tempCards=removeCards(fromCards,tempCards);
				for(int i=0;i<2;i++){
					int index2 = findPair(getNumArray(tempCards),0);
					if(index2==-1) return getBombOrRocket(fromCards);//null;
					int []pair=getCards(tempCards,new CardType(PAIR,index2,2));
					if(pair==null) return getBombOrRocket(fromCards);//null;
					System.arraycopy(pair,0,newCards,4+i*2,2);
					tempCards=removeCards(tempCards,pair);
				}
				java.util.Arrays.sort(newCards);
				return newCards;
			}
			case ROCKET:{
				return null;
			}
			default:return getBombOrRocket(fromCards);//null;
			
	}
	}
	
	public static int[] getCards(int [] cards,CardType cardType){
		if(cards==null||cardType.type==ILLEGAL||cardType.type==UNKNOWN) return null;
		int [] newCards=new int[cardType.cardNum];
		switch(cardType.type){
			case SINGLE:{
				//newCards=new int[1];
				if(cardType.mainCard==13) {newCards[0]=53;return newCards;}
				if(cardType.mainCard==14) {newCards[0]=54;return newCards;} 
				for(int i=0;i<cards.length;i++) 
					if((cards[i]-1)/4==cardType.mainCard) {
						newCards[0]=cards[i];
						return newCards;
					}
				return null;	
			}
			case PAIR:{
				//newCards=new int[2];
				for(int i=0;i<cards.length;i++)
					if((cards[i]-1)/4==cardType.mainCard){
						newCards[0]=cards[i];
						newCards[1]=cards[i+1];
						return newCards;
					}
				return null;	
			}
			case TRIPLET:{
				//newCards=new int[3];
				for(int i=0;i<cards.length;i++)
					if((cards[i]-1)/4==cardType.mainCard){
						newCards[0]=cards[i];
						newCards[1]=cards[i+1];
						newCards[2]=cards[i+2];
						return newCards;
					}
					return null;
			}
			case SEQUENCE:{
				//newCards=new int[cardType.cardNum];
				int start=cardType.mainCard-cardType.cardNum+1;
				for(int i=0,j=0;i<cards.length;i++){
					if((cards[i]-1)/4==start+j) {
						newCards[j]=cards[i];Debug.println("355");Debug.println(""+(cards[i]-1)/4);
						j++;
						if(j==cardType.cardNum) return newCards;
					}
				}
				return null;
			}
			case PAIR_SEQUENCE:{
				//newCards=new int[cardType.cardNum];				
				int length=cardType.cardNum/2;
				int start=cardType.mainCard-length+1;
				/*for(int i=0,j=0;i<cards.length;i++){
					if((cards[i]-1)/4==start+j/2){
						newCards[j++]=cards[i++];
						newCards[j++]=cards[i];
						if(j==cardType.cardNum) return newCards;
					}
				}*/
				for(int i=0;i<length;i++){
					int [] pair=getCards(cards,new CardType(PAIR,start+i,2));
					if(pair==null) return null;
					System.arraycopy(pair,0,newCards,i*2,2);
				}
				java.util.Arrays.sort(newCards);
				return newCards;
			}
			case TRIPLET_SEQUENCE:{
				//newCards=new int[cardType.cardNum];
				int length=cardType.cardNum/3;
				int start=cardType.mainCard-length+1;
				for(int i=0;i<length;i++){
					int [] triplet=getCards(cards,new CardType(TRIPLET,start+i,3));
					if(triplet==null) return null;
					System.arraycopy(triplet,0,newCards,i*3,3);
				}
				java.util.Arrays.sort(newCards);
				return newCards;
			}
			case BOMB:{
				for(int i=0;i<cards.length;i++)
					if((cards[i]-1)/4==cardType.mainCard){
						newCards[0]=cards[i];
						newCards[1]=cards[i+1];
						newCards[2]=cards[i+2];
						newCards[3]=cards[i+3];
						return newCards;
					}
			}
			default: return null;
		}
	}
	
	private static int findSingle(int [] numArray,int from){
		if(numArray==null||from<0||from>=numArray.length) return -1;
		int index = find(1,1,from,15,numArray);
		if(index != -1) return index;
		
		index=findPair(numArray,from);
		if(index!=-1) return index;
		
		index=findTriplet(numArray,from);
		if(index!=-1) return index;
		
		index=findQuad(numArray,from);
		return index;
	}
	
	private static int findPair(int [] numArray,int from){
		if(numArray==null||from<0||from>=numArray.length) return -1;
		
		int index=find(2,2,from,13,numArray);
		if(index!=-1) return index;
		
		index=findTriplet(numArray,from);
		if(index!=-1) return index;
		
		index=findQuad(numArray,from);
		return index;
	}
	
	private static int findTriplet(int [] numArray,int from){
		if(numArray==null||from<0||from>=numArray.length) return -1;
		
		int index=find(3,3,from,13,numArray);
		if(index!=-1) return index;
		
		index=findQuad(numArray,from);
		return index;		
	}
	
	private static int findQuad(int [] numArray,int from){
		if(numArray==null||from<0||from>=numArray.length) return -1;
		
		return find(4,4,from,13,numArray);
	}
	
	private static int findSequence(int [] numArray,int from,int length){
		if(numArray==null||from<0||length<5||length>12||from>12-length) return -1;
		int start,end;
		for(start=from;start<=12-length;){
			start=find(1,4,start,12,numArray);
			if(start==-1) return -1;
			end=find(0,0,start+1,13,numArray);Debug.println("In Rule.findSequence,line:575,start="+start+":end="+end+":numArray:",numArray);
			if(end-start>=length) return start;
			else if(end!=-1) start=end+1;
			else return -1;
		}
		return -1;
	}
	
	private static int findPairSequence(int [] numArray,int from,int length){
		if(numArray==null||from<0||length<3||length>10||from>12-length) return -1;
		int start,end;
		for(start=from;start<12-length;){
			start=find(2,4,start,12,numArray);
			if(start==-1) return -1;
			end=find(0,1,start+1,13,numArray);Debug.println("In Rule.findPairSequence,line:588,start="+start+":end="+end+":numArray:",numArray);
			if(end-start>=length) return start;
			else if(end!=-1) start=end+1;
			else return -1;
		}
		return -1;		
	}
	
	private static int findTripletSequence(int [] numArray,int from,int length){
		if(numArray==null||from<0||length<2||length>6||from>12-length) return -1;
		int start,end;
		for(start=from;start<12-length;){
			start=find(3,4,start,12,numArray);
			if(start==-1) return-1;
			end=find(0,2,start+1,13,numArray);Debug.println("In Rule.findTripletSequence,line:603,start="+start+":end="+end+":numArray:",numArray);
			if(end-start>=length) return start;
			else if(end!=-1) start=end+1;
			else return -1; 
		}
		return -1;
	}
	
	public static int [] removeCards(int [] from,int [] sub){
		if(from==null||sub==null||from.length<sub.length) return null;
		int [] newCards;
		java.util.Arrays.sort(sub);
		java.util.Arrays.sort(from);
		newCards=new int[from.length-sub.length];
		int i=0,j=0,k=0;
		while(i<from.length&&j<sub.length){
			if(from[i]!=sub[j]) newCards[k++]=from[i++];
			else{i++;j++;}
		}
		if(newCards.length-k!=from.length-i) return null;
		System.arraycopy(from,i,newCards,k,from.length-i);
		return newCards;
	}
	
	private static int [] getBomb(int [] from){
		if(from==null) return null;
		
		int index=findQuad(getNumArray(from),0);
		if(index==-1) return null;
		return getCards(from,new CardType(BOMB,index,4));
	}
	
	private static int [] getRocket(int [] from){
		if(from==null||from.length<2) return null;
		if(from[from.length-2]==53&&from[from.length-1]==54){
			int []newCards=new int[2];
			newCards[0]=53;
			newCards[1]=54;
			return newCards;
		}
		return null;
	}
	
	private static int [] getBombOrRocket(int [] from){
		int [] newCards=getBomb(from);
		if(newCards!=null) return newCards;
		return getRocket(from);
		}
	
	public static int [] getSmallCards(int [] cards){
		if(cards==null) return null;
		int newCards;		
		int []numArray=getNumArray(cards);
		int index=find(1,3,0,15,numArray);
		if(index==-1) return getBombOrRocket(cards);
		switch(numArray[index]){
			case 1:return getCards(cards,new CardType(SINGLE,index,1));
			case 2:return getCards(cards,new CardType(PAIR,index,2));
			case 3:return getCards(cards,new CardType(TRIPLET,index,3));
			default:return null;
		}
	}
}	

